Some R packages will need to be installed so that we can see exactly what is going in with our data. Run the code chunk below to install the packages necessary for this activity. If the package is already installed, the script will only load the package without re-installing it.
## First specify the packages of interest
packages = c("sf", "robis","RColorBrewer",
"ggplot2", "dplyr", "leaflet")
## Now load or install&load all
package.check <- lapply(
packages,
FUN = function(x) {
if (!require(x, character.only = TRUE)) {
install.packages(x, dependencies = TRUE)
library(x, character.only = TRUE)
}
}
)
The U.S. has established nearly 1,000 Marine Protected Areas to protect important places in our ocean, estuaries, coastal waters, and Great Lakes. Marine Protected Areas strive to combat climate change, conserve cultural heritage, and protect marine organisms.
Marine protected areas allow for ecological connectivity, and serve as protected “stepping stones” for marine organisms. Let’s make a map so that we can see all of these stepping stones off of the Coast of California.
First, we’ll need to load in some data that has information on all of the Marine Protected Areas in the United States. The data is in the form of a “shape file”. We will load this file and call it “DataBase”.
# loading our database by setting the directory where the shape file lives with the file extension (.shp)
DataBase = st_read("C:/Users/nposd/Documents/Outreach/MPAs/mpa_inventory_2014_public_shp.shp")
Reading layer `mpa_inventory_2014_public_shp' from data source `C:\Users\nposd\Documents\Outreach\MPAs\mpa_inventory_2014_public_shp.shp' using driver `ESRI Shapefile'
Simple feature collection with 1623 features and 24 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -180 ymin: -15.38614 xmax: 180 ymax: 74.70742
Geodetic CRS: WGS 84
For this example, let’s look at the Marine Protected areas off the Coast of California. When looking at our database, we see that there is a column titled “State”, and each row contains the state that the Marine Protected Area is in. We will filter our database to pull out all of the Marine Protected Areas that are in the “State” of “California” using the following code chunk. We will call this new database “California”.
California = filter(DataBase, State == "California")
There are 185 Marine Protected Areas in our California database! Let’s make a map to see all of the boundaries of the Marine Protected Areas. The “geometry” column has the information of the boundaries. The geometry will give us the latitude and longitude, which we will use to plot the boundary of each Marine Protected Area on our map.
To set up the map, we will first map a blank map of the state of California. We will use built-in “leaflet” library to make our map. Let’s set it up so that we can see the ocean topography using the Esri Ocean Basemap. We’ll save our map as “CaliforniaMap”. To print the CaliforniaMap, we’ll type in CaliforniaMap.
CaliforniaMap = leaflet() %>% # start an empty map
addProviderTiles("Esri.OceanBasemap") %>% # add the ocean basemap
fitBounds( -124, 41, -116, 32) # zoom in to the california area
CaliforniaMap # print the map
Nice! Now let’s add the boundaries of all of the Marine Protected Areas that are on the California Coast. We will loop through each individual Marine Protected area, and plot the latitudes and longitudes on our California map, that way, we can see ALL of the Marine Protected Areas on our map together. We will use “addPolygons” to add each Marine Protected Area’s boundary. You can pick the color that you would like to make the boundary in the “color” section of “addPolygons”. For this example, I made the color red, but you can change it to whatever color you would like!
# loop through each MPA and plot the boundaries on our California Map
for(i in 1:length(California$Site_Name)) {
Geo = as.data.frame(California[[25]][[i]][[1]][[1]]) #the geometry is in the 25th column
Longitude = Geo$V1 #Longitude is saved as Variable 1
Latitude = Geo$V2 #Latitude is saved as Variable 2
CaliforniaMap = CaliforniaMap %>%
addPolygons(lng=Longitude,lat=Latitude,
color = "red", # I wanted to make the MPAs red, but you can put any colors you want!
opacity = .5,
fillOpacity = 0.2)
}
CaliforniaMap # print the map
Wow, California has a LOT of Marine Protected Areas! Let’s analyze some data from Marine Protected Areas in California to see exactly how they have helped in the protection of marine organisms! We will need to connect to an online databases to access information about marine organisms.
Let’s choose a specific Marine Protected Area we want to learn more about.
SiteName = ('Soquel Canyon State Marine Conservation Area') #Look at the California data frame in your global environment...
# and choose the MPA you want to learn more about
ChosenMPA = filter(California, Site_Name == SiteName) #filter for that specific MPA
#get the MPA polygon ready
ChosenMPA_hull = st_convex_hull(ChosenMPA$geometry)
ChosenMPA_text = st_as_text(ChosenMPA_hull)
Introduce OBIS here.
SpeciesOccurence = occurrence(geometry = ChosenMPA_text)
Retrieved 5000 records of approximately 7322 (68%)
Retrieved 7322 records of approximately 7322 (100%)
We’re interested in the number of unique species that occur in the chosen MPA. Let’s group our data to find out how many of each species was observed.
# Let's sum up the unique species that occur in the chosen MPA
if ("individualCount" %in% colnames(SpeciesOccurence)){ #if individualCount is an available column..
SpeciesOccurence$individualCount <- suppressWarnings(as.numeric(SpeciesOccurence$individualCount)) #introduces NAs
SpeciesOccurence$individualCount[is.na(SpeciesOccurence$individualCount)] <- 1 #convert NANs to 1; I'm assuming that if it's listed, there was at least one count
SpeciesOccurence$Count <- 1 * SpeciesOccurence$individualCount #make a new column for Counts of each species
} else {
SpeciesOccurence$Count = 1 #if individualCount is not a column, I'm assuming that if it's listed there was at least 1 count
}
It’s time to start visualizing our data!
First let’s look at what time period our samples were from by plotting a histogram of the years the samples were taken.
ggplot(SpeciesOccurence, aes(x=date_year)) + geom_histogram(binwidth = 1)+
labs(title="Histogram of Observation Year", x="Year", y = "Count")

Now let’s look at what depth our samples were from by plotting a histogram of the maximum depth the samples were taken.
ggplot(SpeciesOccurence, aes(x=maximumDepthInMeters)) + geom_histogram(binwidth = 10)+
labs(title="Histogram of Sample Depthr", x="Depth (meters)", y = "Count")

We’ll start with visualizing the different phyla that exist within the MPA. A phylum is a level of classification or taxonmic rank that allows scientists to categrozie animals. Mammals are in the chordate phylum while insects, spiders, millipeds, and crustaceans are in the arthropod phylum. Let’s look to see what phyla exist in this MPA.

Let’s look at the top then animals that were observed in the MPA.
animals = filter(SpeciesOccurence, kingdom == "Animalia") #filtering the dataframe to pull out the animals
TenAnimals = data.frame(sort(table(animals$scientificName), decreasing = TRUE)[1:10]) #finding the 10 animals that occur most often in the dataframe
print(TenAnimals)
Now let’s take a look at the most common animal in the MPA and see when it occured.
MostCommon_Animal = filter(SpeciesOccurence, scientificName == TenAnimals$Var1[[1]]) #filter for the most commonly occuring animal
Warning messages:
1: In readChar(file, size, TRUE) : truncating string with embedded nuls
2: In readChar(file, size, TRUE) : truncating string with embedded nuls
3: In readChar(file, size, TRUE) : truncating string with embedded nuls
4: In readChar(file, size, TRUE) : truncating string with embedded nuls
5: In readChar(file, size, TRUE) : truncating string with embedded nuls
6: In readChar(file, size, TRUE) : truncating string with embedded nuls
7: In readChar(file, size, TRUE) : truncating string with embedded nuls
8: In readChar(file, size, TRUE) : truncating string with embedded nuls
#Plot the most commonly occuring animal in the MPA over time to see when it occured and how many of them were observed at that time
ggplot(MostCommon_Animal, aes(x = date_year)) +
geom_histogram(color = "darkblue", fill = "lightblue") +
labs(title = "Histogram of Most Commonly Occuring Animal in the MPA", x = "Year", y = "# of Kelp Bass") # make a histogram showing the most commonly occuring animal

LS0tDQp0aXRsZTogIk1hcmluZSBQcm90ZWN0ZWQgQXJlYSBBY3Rpdml0eSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClNvbWUgUiBwYWNrYWdlcyB3aWxsIG5lZWQgdG8gYmUgaW5zdGFsbGVkIHNvIHRoYXQgd2UgY2FuIHNlZSBleGFjdGx5IHdoYXQgaXMgZ29pbmcgaW4gd2l0aCBvdXIgZGF0YS4gUnVuIHRoZSBjb2RlIGNodW5rIGJlbG93IHRvIGluc3RhbGwgdGhlIHBhY2thZ2VzIG5lY2Vzc2FyeSBmb3IgdGhpcyBhY3Rpdml0eS4gSWYgdGhlIHBhY2thZ2UgaXMgYWxyZWFkeSBpbnN0YWxsZWQsIHRoZSBzY3JpcHQgd2lsbCBvbmx5IGxvYWQgdGhlIHBhY2thZ2Ugd2l0aG91dCByZS1pbnN0YWxsaW5nIGl0Lg0KDQpgYGB7cn0NCiMjIEZpcnN0IHNwZWNpZnkgdGhlIHBhY2thZ2VzIG9mIGludGVyZXN0IC0tIGlmIHlvdSBuZWVkIHRvIGFueSBwYWNrYWdlcyBpbiB0aGUgZnV0dXJlLCBhZGQgdGhlbSBoZXJlDQpwYWNrYWdlcyA9IGMoInNmIiwgInJvYmlzIiwiUkNvbG9yQnJld2VyIiwNCiAgICAgICAgICAgICAiZ2dwbG90MiIsICJkcGx5ciIsICJsZWFmbGV0IikNCg0KIyMgTm93IGxvYWQgb3IgaW5zdGFsbCZsb2FkIGFsbA0KcGFja2FnZS5jaGVjayA8LSBsYXBwbHkoDQogIHBhY2thZ2VzLA0KICBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgaWYgKCFyZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpIHsNCiAgICAgIGluc3RhbGwucGFja2FnZXMoeCwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgICAgIGxpYnJhcnkoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQ0KICAgIH0NCiAgfQ0KKQ0KYGBgDQoNClRoZSBVLlMuIGhhcyBlc3RhYmxpc2hlZCBuZWFybHkgMSwwMDAgTWFyaW5lIFByb3RlY3RlZCBBcmVhcyB0byBwcm90ZWN0IGltcG9ydGFudCBwbGFjZXMgaW4gb3VyIG9jZWFuLCBlc3R1YXJpZXMsIGNvYXN0YWwgd2F0ZXJzLCBhbmQgR3JlYXQgTGFrZXMuIE1hcmluZSBQcm90ZWN0ZWQgQXJlYXMgc3RyaXZlIHRvIGNvbWJhdCBjbGltYXRlIGNoYW5nZSwgY29uc2VydmUgY3VsdHVyYWwgaGVyaXRhZ2UsIGFuZCBwcm90ZWN0IG1hcmluZSBvcmdhbmlzbXMuIA0KDQpNYXJpbmUgcHJvdGVjdGVkIGFyZWFzIGFsbG93IGZvciBlY29sb2dpY2FsIGNvbm5lY3Rpdml0eSwgYW5kIHNlcnZlIGFzIHByb3RlY3RlZCAic3RlcHBpbmcgc3RvbmVzIiBmb3IgbWFyaW5lIG9yZ2FuaXNtcy4gTGV0J3MgbWFrZSBhIG1hcCBzbyB0aGF0IHdlIGNhbiBzZWUgYWxsIG9mIHRoZXNlIHN0ZXBwaW5nIHN0b25lcyBvZmYgb2YgdGhlIENvYXN0IG9mIENhbGlmb3JuaWEuDQoNCkZpcnN0LCB3ZSdsbCBuZWVkIHRvIGxvYWQgaW4gc29tZSBkYXRhIHRoYXQgaGFzIGluZm9ybWF0aW9uIG9uIGFsbCBvZiB0aGUgTWFyaW5lIFByb3RlY3RlZCBBcmVhcyBpbiB0aGUgVW5pdGVkIFN0YXRlcy4gVGhlIGRhdGEgaXMgaW4gdGhlIGZvcm0gb2YgYSAic2hhcGUgZmlsZSIuIFdlIHdpbGwgbG9hZCB0aGlzIGZpbGUgYW5kIGNhbGwgaXQgIkRhdGFCYXNlIi4gDQoNCmBgYHtyfQ0KIyBsb2FkaW5nIG91ciBkYXRhYmFzZSBieSBzZXR0aW5nIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIHNoYXBlIGZpbGUgbGl2ZXMgd2l0aCB0aGUgZmlsZSBleHRlbnNpb24gKC5zaHApDQpEYXRhQmFzZSA9IHN0X3JlYWQoIkM6L1VzZXJzL25wb3NkL0RvY3VtZW50cy9PdXRyZWFjaC9NUEFzL21wYV9pbnZlbnRvcnlfMjAxNF9wdWJsaWNfc2hwLnNocCIpDQpgYGANCg0KRm9yIHRoaXMgZXhhbXBsZSwgbGV0J3MgbG9vayBhdCB0aGUgTWFyaW5lIFByb3RlY3RlZCBhcmVhcyBvZmYgdGhlIENvYXN0IG9mIENhbGlmb3JuaWEuIFdoZW4gbG9va2luZyBhdCBvdXIgZGF0YWJhc2UsIHdlIHNlZSB0aGF0IHRoZXJlIGlzIGEgY29sdW1uIHRpdGxlZCAiU3RhdGUiLCBhbmQgZWFjaCByb3cgY29udGFpbnMgdGhlIHN0YXRlIHRoYXQgdGhlIE1hcmluZSBQcm90ZWN0ZWQgQXJlYSBpcyBpbi4gV2Ugd2lsbCBmaWx0ZXIgb3VyIGRhdGFiYXNlIHRvIHB1bGwgb3V0IGFsbCBvZiB0aGUgTWFyaW5lIFByb3RlY3RlZCBBcmVhcyB0aGF0IGFyZSBpbiB0aGUgIlN0YXRlIiBvZiAiQ2FsaWZvcm5pYSIgdXNpbmcgdGhlIGZvbGxvd2luZyBjb2RlIGNodW5rLiBXZSB3aWxsIGNhbGwgdGhpcyBuZXcgZGF0YWJhc2UgIkNhbGlmb3JuaWEiLiANCg0KYGBge3J9DQpDYWxpZm9ybmlhID0gZmlsdGVyKERhdGFCYXNlLCBTdGF0ZSA9PSAiQ2FsaWZvcm5pYSIpDQpgYGANCg0KVGhlcmUgYXJlIDE4NSBNYXJpbmUgUHJvdGVjdGVkIEFyZWFzIGluIG91ciBDYWxpZm9ybmlhIGRhdGFiYXNlISBMZXQncyBtYWtlIGEgbWFwIHRvIHNlZSBhbGwgb2YgdGhlIGJvdW5kYXJpZXMgb2YgdGhlIE1hcmluZSBQcm90ZWN0ZWQgQXJlYXMuIFRoZSAiZ2VvbWV0cnkiIGNvbHVtbiBoYXMgdGhlIGluZm9ybWF0aW9uIG9mIHRoZSBib3VuZGFyaWVzLiBUaGUgZ2VvbWV0cnkgd2lsbCBnaXZlIHVzIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlLCB3aGljaCB3ZSB3aWxsIHVzZSB0byBwbG90IHRoZSBib3VuZGFyeSBvZiBlYWNoIE1hcmluZSBQcm90ZWN0ZWQgQXJlYSBvbiBvdXIgbWFwLiANCg0KVG8gc2V0IHVwIHRoZSBtYXAsIHdlIHdpbGwgZmlyc3QgbWFwIGEgYmxhbmsgbWFwIG9mIHRoZSBzdGF0ZSBvZiBDYWxpZm9ybmlhLiBXZSB3aWxsIHVzZSBidWlsdC1pbiAibGVhZmxldCIgbGlicmFyeSB0byBtYWtlIG91ciBtYXAuIExldCdzIHNldCBpdCB1cCBzbyB0aGF0IHdlIGNhbiBzZWUgdGhlIG9jZWFuIHRvcG9ncmFwaHkgdXNpbmcgdGhlIEVzcmkgT2NlYW4gQmFzZW1hcC4gV2UnbGwgc2F2ZSBvdXIgbWFwIGFzICJDYWxpZm9ybmlhTWFwIi4gVG8gcHJpbnQgdGhlIENhbGlmb3JuaWFNYXAsIHdlJ2xsIHR5cGUgaW4gQ2FsaWZvcm5pYU1hcC4gDQoNCmBgYHtyfQ0KQ2FsaWZvcm5pYU1hcCA9IGxlYWZsZXQoKSAlPiUgIyBzdGFydCBhbiBlbXB0eSBtYXANCiAgIGFkZFByb3ZpZGVyVGlsZXMoIkVzcmkuT2NlYW5CYXNlbWFwIikgJT4lICMgYWRkIHRoZSBvY2VhbiBiYXNlbWFwIA0KICAgZml0Qm91bmRzKCAtMTI0LCA0MSwgLTExNiwgMzIpICMgem9vbSBpbiB0byB0aGUgY2FsaWZvcm5pYSBhcmVhDQoNCkNhbGlmb3JuaWFNYXAgIyBwcmludCB0aGUgbWFwDQpgYGANCk5pY2UhIE5vdyBsZXQncyBhZGQgdGhlIGJvdW5kYXJpZXMgb2YgYWxsIG9mIHRoZSBNYXJpbmUgUHJvdGVjdGVkIEFyZWFzIHRoYXQgYXJlIG9uIHRoZSBDYWxpZm9ybmlhIENvYXN0LiBXZSB3aWxsIGxvb3AgdGhyb3VnaCBlYWNoIGluZGl2aWR1YWwgTWFyaW5lIFByb3RlY3RlZCBhcmVhLCBhbmQgcGxvdCB0aGUgbGF0aXR1ZGVzIGFuZCBsb25naXR1ZGVzIG9uIG91ciBDYWxpZm9ybmlhIG1hcCwgdGhhdCB3YXksIHdlIGNhbiBzZWUgQUxMIG9mIHRoZSBNYXJpbmUgUHJvdGVjdGVkIEFyZWFzIG9uIG91ciBtYXAgdG9nZXRoZXIuIFdlIHdpbGwgdXNlICJhZGRQb2x5Z29ucyIgdG8gYWRkIGVhY2ggTWFyaW5lIFByb3RlY3RlZCBBcmVhJ3MgYm91bmRhcnkuIFlvdSBjYW4gcGljayB0aGUgY29sb3IgdGhhdCB5b3Ugd291bGQgbGlrZSB0byBtYWtlIHRoZSBib3VuZGFyeSBpbiB0aGUgImNvbG9yIiBzZWN0aW9uIG9mICJhZGRQb2x5Z29ucyIuIEZvciB0aGlzIGV4YW1wbGUsIEkgbWFkZSB0aGUgY29sb3IgcmVkLCBidXQgeW91IGNhbiBjaGFuZ2UgaXQgdG8gd2hhdGV2ZXIgY29sb3IgeW91IHdvdWxkIGxpa2UhDQoNCmBgYHtyfQ0KDQojIGxvb3AgdGhyb3VnaCBlYWNoIE1QQSBhbmQgcGxvdCB0aGUgYm91bmRhcmllcyBvbiBvdXIgQ2FsaWZvcm5pYSBNYXANCmZvcihpIGluIDE6bGVuZ3RoKENhbGlmb3JuaWEkU2l0ZV9OYW1lKSkgew0KR2VvID0gYXMuZGF0YS5mcmFtZShDYWxpZm9ybmlhW1syNV1dW1tpXV1bWzFdXVtbMV1dKSAjdGhlIGdlb21ldHJ5IGlzIGluIHRoZSAyNXRoIGNvbHVtbg0KTG9uZ2l0dWRlID0gR2VvJFYxICNMb25naXR1ZGUgaXMgc2F2ZWQgYXMgVmFyaWFibGUgMQ0KTGF0aXR1ZGUgPSBHZW8kVjIgI0xhdGl0dWRlIGlzIHNhdmVkIGFzIFZhcmlhYmxlIDINCkNhbGlmb3JuaWFNYXAgPSBDYWxpZm9ybmlhTWFwICAlPiUgDQogICAgICAgYWRkUG9seWdvbnMobG5nPUxvbmdpdHVkZSxsYXQ9TGF0aXR1ZGUsIA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsICMgSSB3YW50ZWQgdG8gbWFrZSB0aGUgTVBBcyByZWQsIGJ1dCB5b3UgY2FuIHB1dCBhbnkgY29sb3JzIHlvdSB3YW50IQ0KICAgICAgICAgICAgICAgICAgIG9wYWNpdHkgPSAuNSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjIpDQp9DQoNCkNhbGlmb3JuaWFNYXAgIyBwcmludCB0aGUgbWFwDQpgYGANCg0KV293LCBDYWxpZm9ybmlhIGhhcyBhIExPVCBvZiBNYXJpbmUgUHJvdGVjdGVkIEFyZWFzISBMZXQncyBhbmFseXplIHNvbWUgZGF0YSBmcm9tIE1hcmluZSBQcm90ZWN0ZWQgQXJlYXMgaW4gQ2FsaWZvcm5pYSB0byBzZWUgZXhhY3RseSBob3cgdGhleSBoYXZlIGhlbHBlZCBpbiB0aGUgcHJvdGVjdGlvbiBvZiBtYXJpbmUgb3JnYW5pc21zISBXZSB3aWxsIG5lZWQgdG8gY29ubmVjdCB0byBhbiBvbmxpbmUgZGF0YWJhc2VzIHRvIGFjY2VzcyBpbmZvcm1hdGlvbiBhYm91dCBtYXJpbmUgb3JnYW5pc21zLiANCg0KTGV0J3MgY2hvb3NlIGEgc3BlY2lmaWMgTWFyaW5lIFByb3RlY3RlZCBBcmVhIHdlIHdhbnQgdG8gbGVhcm4gbW9yZSBhYm91dC4gDQpgYGB7cn0NClNpdGVOYW1lID0gKCdTb3F1ZWwgQ2FueW9uIFN0YXRlIE1hcmluZSBDb25zZXJ2YXRpb24gQXJlYScpICAjTG9vayBhdCB0aGUgQ2FsaWZvcm5pYSBkYXRhIGZyYW1lIGluIHlvdXIgZ2xvYmFsIGVudmlyb25tZW50Li4uDQojIGFuZCBjaG9vc2UgdGhlIE1QQSB5b3Ugd2FudCB0byBsZWFybiBtb3JlIGFib3V0DQpDaG9zZW5NUEEgPSBmaWx0ZXIoQ2FsaWZvcm5pYSwgU2l0ZV9OYW1lID09IFNpdGVOYW1lKSAjZmlsdGVyIGZvciB0aGF0IHNwZWNpZmljIE1QQQ0KI2dldCB0aGUgTVBBIHBvbHlnb24gcmVhZHkNCkNob3Nlbk1QQV9odWxsID0gc3RfY29udmV4X2h1bGwoQ2hvc2VuTVBBJGdlb21ldHJ5KQ0KQ2hvc2VuTVBBX3RleHQgPSBzdF9hc190ZXh0KENob3Nlbk1QQV9odWxsKQ0KYGBgDQoNCkludHJvZHVjZSBPQklTIGhlcmUuDQpgYGB7cn0NClNwZWNpZXNPY2N1cmVuY2UgPSBvY2N1cnJlbmNlKGdlb21ldHJ5ID0gQ2hvc2VuTVBBX3RleHQpDQpgYGANCg0KV2UncmUgaW50ZXJlc3RlZCBpbiB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBzcGVjaWVzIHRoYXQgb2NjdXIgaW4gdGhlIGNob3NlbiBNUEEuIExldCdzIGdyb3VwIG91ciBkYXRhIHRvIGZpbmQgb3V0IGhvdyBtYW55IG9mIGVhY2ggc3BlY2llcyB3YXMgb2JzZXJ2ZWQuIA0KYGBge3J9DQppZiAoImluZGl2aWR1YWxDb3VudCIgJWluJSBjb2xuYW1lcyhTcGVjaWVzT2NjdXJlbmNlKSl7ICNpZiBpbmRpdmlkdWFsQ291bnQgaXMgYW4gYXZhaWxhYmxlIGNvbHVtbi4uDQogIFNwZWNpZXNPY2N1cmVuY2UkaW5kaXZpZHVhbENvdW50IDwtIHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhTcGVjaWVzT2NjdXJlbmNlJGluZGl2aWR1YWxDb3VudCkpICNpbnRyb2R1Y2VzIE5Bcw0KICBTcGVjaWVzT2NjdXJlbmNlJGluZGl2aWR1YWxDb3VudFtpcy5uYShTcGVjaWVzT2NjdXJlbmNlJGluZGl2aWR1YWxDb3VudCldIDwtIDEgI2NvbnZlcnQgTkFOcyB0byAxOyBJJ20gYXNzdW1pbmcgdGhhdCBpZiBpdCdzIGxpc3RlZCwgdGhlcmUgd2FzIGF0IGxlYXN0IG9uZSBjb3VudA0KICBTcGVjaWVzT2NjdXJlbmNlJENvdW50IDwtIDEgKiBTcGVjaWVzT2NjdXJlbmNlJGluZGl2aWR1YWxDb3VudCAjbWFrZSBhIG5ldyBjb2x1bW4gZm9yIENvdW50cyBvZiBlYWNoIHNwZWNpZXMNCn0gZWxzZSB7DQogIFNwZWNpZXNPY2N1cmVuY2UkQ291bnQgPSAxICNpZiBpbmRpdmlkdWFsQ291bnQgaXMgbm90IGEgY29sdW1uLCBJJ20gYXNzdW1pbmcgdGhhdCBpZiBpdCdzIGxpc3RlZCB0aGVyZSB3YXMgYXQgbGVhc3QgMSBjb3VudA0KfQ0KYGBgDQoNCkl0J3MgdGltZSB0byBzdGFydCB2aXN1YWxpemluZyBvdXIgZGF0YSENCg0KRmlyc3QgbGV0J3MgbG9vayBhdCB3aGF0IHRpbWUgcGVyaW9kIG91ciBzYW1wbGVzIHdlcmUgZnJvbSBieSBwbG90dGluZyBhIGhpc3RvZ3JhbSBvZiB0aGUgeWVhcnMgdGhlIHNhbXBsZXMgd2VyZSB0YWtlbi4NCmBgYHtyfQ0KZ2dwbG90KFNwZWNpZXNPY2N1cmVuY2UsIGFlcyh4PWRhdGVfeWVhcikpICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSsNCiAgbGFicyh0aXRsZT0iSGlzdG9ncmFtIG9mIE9ic2VydmF0aW9uIFllYXIiLCB4PSJZZWFyIiwgeSA9ICJDb3VudCIpDQpgYGANCg0KTm93IGxldCdzIGxvb2sgYXQgd2hhdCBkZXB0aCBvdXIgc2FtcGxlcyB3ZXJlIGZyb20gYnkgcGxvdHRpbmcgYSBoaXN0b2dyYW0gb2YgdGhlIG1heGltdW0gZGVwdGggdGhlIHNhbXBsZXMgd2VyZSB0YWtlbi4NCmBgYHtyfQ0KZ2dwbG90KFNwZWNpZXNPY2N1cmVuY2UsIGFlcyh4PW1heGltdW1EZXB0aEluTWV0ZXJzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwKSsNCiAgbGFicyh0aXRsZT0iSGlzdG9ncmFtIG9mIE1heGltdW0gU2FtcGxlIERlcHRoIGluIG1ldGVycyIsIHg9IkRlcHRoIChtZXRlcnMpIiwgeSA9ICJDb3VudCIpDQpgYGANCg0KV2UnbGwgc3RhcnQgd2l0aCB2aXN1YWxpemluZyB0aGUgZGlmZmVyZW50IHBoeWxhIHRoYXQgZXhpc3Qgd2l0aGluIHRoZSBNUEEuIEEgcGh5bHVtIGlzIGEgbGV2ZWwgb2YgY2xhc3NpZmljYXRpb24gb3IgdGF4b25taWMgcmFuayB0aGF0IGFsbG93cyBzY2llbnRpc3RzIHRvIGNhdGVncm96aWUgYW5pbWFscy4gTWFtbWFscyBhcmUgaW4gdGhlIGNob3JkYXRlIHBoeWx1bSB3aGlsZSBpbnNlY3RzLCBzcGlkZXJzLCBtaWxsaXBlZHMsIGFuZCBjcnVzdGFjZWFucyBhcmUgaW4gdGhlIGFydGhyb3BvZCBwaHlsdW0uIExldCdzIGxvb2sgdG8gc2VlIHdoYXQgcGh5bGEgZXhpc3QgaW4gdGhpcyBNUEEuDQoNCmBgYHtyfQ0KUGh5bHVtIDwtIGFnZ3JlZ2F0ZShTcGVjaWVzT2NjdXJlbmNlJENvdW50LCBieT1saXN0KENhdGVnb3J5PVNwZWNpZXNPY2N1cmVuY2UkcGh5bHVtKSxGVU49c3VtKSAjYWdncmVnYXRlIHRoZSBkYXRhIGJ5IHBoeWxhDQoNCiNDcmVhdGUgYSBwaWUgY2hhcnQgdG8gdmlzdWFsaXplIHRoZSBwcm9wb3J0aW9uIG9mIHBoeWxhIGZvdW5kIGluIHRoZSBNUEENCiNmaW5kIHRoZSBwZXJjZW50YWdlcyBmb3IgZWFjaCBwaHlsYQ0KZGF0YSA9IFBoeWx1bSAlPiUgDQogIG11dGF0ZShwZXI9eC9zdW0oeCkpICU+JSANCiAgYXJyYW5nZShkZXNjKENhdGVnb3J5KSkNCmRhdGEkbGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQoZGF0YSRwZXIpDQoNCiNQbG90IHRoZSBwaWUgY2hhcnQgYW5kIG9ubHkgZGlzcGxheSB0aGUgcGVyY2VudGFnZXMgaWYgdGhlcmUgYXJlIGxlc3MgdGhhbiA4IHBoeWxhIHNvIGl0IGRvZXNuJ3QgZ2V0IHRvbyBjcm93ZGVkIG9uIHRoZSBwaWUgY2hhcnQNCmlmIChucm93KGRhdGEpID4gOCl7DQogIGdncGxvdChkYXRhPWRhdGEpKw0KICBnZW9tX2JhcihhZXMoeD0iIiwgeT1wZXIsIGZpbGw9Q2F0ZWdvcnkpLCBzdGF0PSJpZGVudGl0eSIsIHdpZHRoID0gMSkrDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkrDQogIHRoZW1lX3ZvaWQoKSsNCiAgZ2d0aXRsZSgiUHJvcG9ydGlvbiBvZiBQaHlsYSBpbiBNUEEgb2YgSW50ZXJlc3QiKQ0KfWVsc2V7DQogIGdncGxvdChkYXRhPWRhdGEpKw0KICBnZW9tX2JhcihhZXMoeD0iIiwgeT1wZXIsIGZpbGw9Q2F0ZWdvcnkpLCBzdGF0PSJpZGVudGl0eSIsIHdpZHRoID0gMSkrDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkrDQogIHRoZW1lX3ZvaWQoKStnZW9tX3RleHQoYWVzKHg9MSwgeSA9IGN1bXN1bShwZXIpIC0gcGVyLzIsIGxhYmVsPWxhYmVsKSkrDQogIGdndGl0bGUoIlByb3BvcnRpb24gb2YgUGh5bGEgaW4gTVBBIG9mIEludGVyZXN0IikNCn0NCmBgYA0KDQpMZXQncyBsb29rIGF0IHRoZSB0b3AgdGhlbiBhbmltYWxzIHRoYXQgd2VyZSBvYnNlcnZlZCBpbiB0aGUgTVBBLg0KYGBge3J9DQphbmltYWxzID0gZmlsdGVyKFNwZWNpZXNPY2N1cmVuY2UsIGtpbmdkb20gPT0gIkFuaW1hbGlhIikgI2ZpbHRlcmluZyB0aGUgZGF0YWZyYW1lIHRvIHB1bGwgb3V0IHRoZSBhbmltYWxzDQpUZW5BbmltYWxzID0gZGF0YS5mcmFtZShzb3J0KHRhYmxlKGFuaW1hbHMkc2NpZW50aWZpY05hbWUpLCBkZWNyZWFzaW5nID0gVFJVRSlbMToxMF0pICNmaW5kaW5nIHRoZSAxMCBhbmltYWxzIHRoYXQgb2NjdXIgbW9zdCBvZnRlbiBpbiB0aGUgZGF0YWZyYW1lDQpwcmludChUZW5BbmltYWxzKQ0KYGBgDQoNCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgbW9zdCBjb21tb24gYW5pbWFsIGluIHRoZSBNUEEgYW5kIHNlZSB3aGVuIGl0IG9jY3VyZWQuDQpgYGB7cn0NCk1vc3RDb21tb25fQW5pbWFsID0gZmlsdGVyKFNwZWNpZXNPY2N1cmVuY2UsIHNjaWVudGlmaWNOYW1lID09IFRlbkFuaW1hbHMkVmFyMVtbMV1dKSAjZmlsdGVyIGZvciB0aGUgbW9zdCBjb21tb25seSBvY2N1cmluZyBhbmltYWwNCg0KI1Bsb3QgdGhlIG1vc3QgY29tbW9ubHkgb2NjdXJpbmcgYW5pbWFsIGluIHRoZSBNUEEgb3ZlciB0aW1lIHRvIHNlZSB3aGVuIGl0IG9jY3VyZWQgYW5kIGhvdyBtYW55IG9mIHRoZW0gd2VyZSBvYnNlcnZlZCBhdCB0aGF0IHRpbWUNCmdncGxvdChNb3N0Q29tbW9uX0FuaW1hbCwgYWVzKHggPSBkYXRlX3llYXIpKSArIA0KICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICJkYXJrYmx1ZSIsIGZpbGwgPSAibGlnaHRibHVlIikgKyANCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgTW9zdCBDb21tb25seSBPY2N1cmluZyBBbmltYWwgaW4gdGhlIE1QQSIsIHggPSAiWWVhciIsIHkgPSAiIyBvZiBLZWxwIEJhc3MiKSAjIG1ha2UgYSBoaXN0b2dyYW0gc2hvd2luZyB0aGUgbW9zdCBjb21tb25seSBvY2N1cmluZyBhbmltYWwNCmBgYA0KDQoNCg==